import BasePlugin from './BasePlugin';

/**
 * 裁剪插件 - 处理图像裁剪
 */
export default class CropPlugin extends BasePlugin {
    constructor() {
        super();
        this.isCropping = false;
        this.cropRect = null;
        this.originalImage = null;
        this.cropZone = null;
        this.cropBorder = {
            color: '#0099ff',
            width: 2,
            dash: [5, 5]
        };
        this.cropCorner = {
            size: 10,
            color: '#0099ff',
            strokeWidth: 2
        };
    }

    /**
     * 初始化插件
     */
    init(editor) {
        super.init(editor);
        this._setupEventListeners();
    }

    /**
     * 启动裁剪模式
     */
    startCropping(imageObject) {
        if (!this.isEnabled() || !this.canvas || !imageObject || this.isCropping) return;

        this.isCropping = true;
        this.originalImage = imageObject;

        // 禁用其他对象的选择和交互
        this.canvas.getObjects().forEach(obj => {
            if (obj !== imageObject) {
                obj.selectable = false;
                obj.evented = false;
            }
        });

        // 创建裁剪区域
        const imgBounds = imageObject.getBoundingRect();
        this.cropRect = {
            left: imgBounds.left,
            top: imgBounds.top,
            width: imgBounds.width,
            height: imgBounds.height
        };

        this._createCropZone();
        this.canvas.renderAll();

        this._emitCropEvent('start');
    }

    /**
     * 应用裁剪
     */
    applyCrop() {
        if (!this.isEnabled() || !this.isCropping || !this.originalImage || !this.cropZone) return;

        // 获取裁剪区域相对于图片的坐标
        const imgElement = this.originalImage.getElement();
        const cropRect = this._getCropRect();

        // 创建临时画布进行裁剪
        const tempCanvas = document.createElement('canvas');
        const tempCtx = tempCanvas.getContext('2d');

        // 设置临时画布大小为裁剪区域大小
        tempCanvas.width = cropRect.width;
        tempCanvas.height = cropRect.height;

        // 在临时画布上绘制裁剪后的图像
        tempCtx.drawImage(
            imgElement,
            cropRect.x,
            cropRect.y,
            cropRect.width,
            cropRect.height,
            0,
            0,
            cropRect.width,
            cropRect.height
        );

        // 创建新图片对象
        fabric.Image.fromURL(tempCanvas.toDataURL(), (newImage) => {
            // 设置新图片的位置和缩放
            newImage.set({
                left: this.cropZone.left,
                top: this.cropZone.top,
                scaleX: this.cropZone.width / cropRect.width,
                scaleY: this.cropZone.height / cropRect.height
            });

            // 替换原图片
            this.canvas.remove(this.originalImage);
            this.canvas.add(newImage);
            this.canvas.setActiveObject(newImage);

            this.endCropping();
            this._emitCropEvent('apply', newImage);
        });
    }

    /**
     * 取消裁剪
     */
    cancelCrop() {
        if (!this.isEnabled() || !this.isCropping) return;
        this.endCropping();
        this._emitCropEvent('cancel');
    }

    /**
     * 结束裁剪模式
     */
    endCropping() {
        if (!this.isEnabled() || !this.isCropping) return;

        // 移除裁剪区域
        if (this.cropZone) {
            this.canvas.remove(this.cropZone);
            this.cropZone = null;
        }

        // 恢复其他对象的选择和交互
        this.canvas.getObjects().forEach(obj => {
            obj.selectable = true;
            obj.evented = true;
        });

        this.isCropping = false;
        this.originalImage = null;
        this.cropRect = null;

        this.canvas.renderAll();
        this._emitCropEvent('end');
    }

    /**
     * 创建裁剪区域
     */
    _createCropZone() {
        // 创建裁剪区域矩形
        this.cropZone = new fabric.Rect({
            left: this.cropRect.left,
            top: this.cropRect.top,
            width: this.cropRect.width,
            height: this.cropRect.height,
            fill: 'rgba(0,0,0,0.3)',
            stroke: this.cropBorder.color,
            strokeWidth: this.cropBorder.width,
            strokeDashArray: this.cropBorder.dash,
            cornerColor: this.cropCorner.color,
            cornerSize: this.cropCorner.size,
            cornerStrokeColor: this.cropCorner.color,
            transparentCorners: false,
            hasRotatingPoint: false
        });

        // 限制裁剪区域在图片范围内
        this.cropZone.on('moving', this._constrainCropZone.bind(this));
        this.cropZone.on('scaling', this._constrainCropZone.bind(this));

        this.canvas.add(this.cropZone);
        this.canvas.setActiveObject(this.cropZone);
    }

    /**
     * 限制裁剪区域在图片范围内
     */
    _constrainCropZone(e) {
        const cropZone = e.target;
        const imgBounds = this.originalImage.getBoundingRect();

        // 获取裁剪区域的边界
        const cropBounds = cropZone.getBoundingRect();

        // 限制左边界
        if (cropBounds.left < imgBounds.left) {
            cropZone.left += imgBounds.left - cropBounds.left;
        }

        // 限制上边界
        if (cropBounds.top < imgBounds.top) {
            cropZone.top += imgBounds.top - cropBounds.top;
        }

        // 限制右边界
        if (cropBounds.left + cropBounds.width > imgBounds.left + imgBounds.width) {
            if (e.transform.action === 'scaling') {
                cropZone.scaleX *= (imgBounds.width - (cropBounds.left - imgBounds.left)) / cropBounds.width;
            } else {
                cropZone.left = imgBounds.left + imgBounds.width - cropBounds.width;
            }
        }

        // 限制下边界
        if (cropBounds.top + cropBounds.height > imgBounds.top + imgBounds.height) {
            if (e.transform.action === 'scaling') {
                cropZone.scaleY *= (imgBounds.height - (cropBounds.top - imgBounds.top)) / cropBounds.height;
            } else {
                cropZone.top = imgBounds.top + imgBounds.height - cropBounds.height;
            }
        }
    }

    /**
     * 获取裁剪区域相对于图片的坐标和尺寸
     */
    _getCropRect() {
        const imgBounds = this.originalImage.getBoundingRect();
        const cropBounds = this.cropZone.getBoundingRect();

        return {
            x: (cropBounds.left - imgBounds.left) / this.originalImage.scaleX,
            y: (cropBounds.top - imgBounds.top) / this.originalImage.scaleY,
            width: cropBounds.width / this.originalImage.scaleX,
            height: cropBounds.height / this.originalImage.scaleY
        };
    }

    /**
     * 发送裁剪事件
     */
    _emitCropEvent(type, target = null) {
        this.editor.emit('crop:applied', {
            type,
            target,
            cropRect: type === 'apply' ? this._getCropRect() : null
        });
    }

    /**
     * 设置事件监听
     */
    _setupEventListeners() {
        if (!this.canvas) return;

        // 监听对象选择事件
        this.canvas.on('selection:created', (e) => {
            if (!this.isEnabled() || this.isCropping) return;

            const activeObject = e.target;
            if (activeObject instanceof fabric.Image) {
                this.editor.emit('crop:selectable', true);
            }
        });

        this.canvas.on('selection:updated', (e) => {
            if (!this.isEnabled() || this.isCropping) return;

            const activeObject = e.target;
            if (activeObject instanceof fabric.Image) {
                this.editor.emit('crop:selectable', true);
            } else {
                this.editor.emit('crop:selectable', false);
            }
        });

        this.canvas.on('selection:cleared', () => {
            if (!this.isEnabled() || this.isCropping) return;
            this.editor.emit('crop:selectable', false);
        });

        // 监听键盘事件
        document.addEventListener('keydown', (e) => {
            if (!this.isEnabled() || !this.isCropping) return;

            if (e.key === 'Escape') {
                this.cancelCrop();
            } else if (e.key === 'Enter') {
                this.applyCrop();
            }
        });
    }

    /**
     * 销毁插件
     */
    destroy() {
        if (this.canvas) {
            if (this.isCropping) {
                this.endCropping();
            }
            document.removeEventListener('keydown', this._handleKeyDown);
        }
        super.destroy();
    }
} 